import socket, sqlite3, crypt
import threading
from BlueMarble import *
from GameUser import *
from random import randint
#기본 socket 커넥션 설정
HOST = ''
PORT = 8112
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
users = []
login_users = {}
game_users_socket = {}
game_users = {}
game_user_count = 0 #게임에 접속한 유저수
blue_marble = BlueMarble()
#sql3를 사용하기 위해 테이블과 데이터베이스 생성
con = sqlite3.connect('member.db')
cur = con.cursor()
#유저의 id를 유니크하게 primary key 설정
query = 'CREATE TABLE members(id TEXT PRIMARY KEY, password TEXT );'
try:#초기 테이블 생성 시도후 존재하면 pass
    cur.execute(query) #데이터베이스 초기 테이블 생성
    cur.commit()
except:
    pass

def service(conn):
    global game_user_count, blue_marble, game_users
    connect = sqlite3.connect('member.db') #같은 쓰레드내에서만 데이터베이스 커서가 공유되기에 다시 db 연결
    cursor = connect.cursor()
    try:
        while conn:
            recv_data = conn.recv(1024) #사용자가 보내는 데이터 받기
            recv_data = recv_data.decode('utf-8')
            print(">> " + recv_data)
            ready = False
            recv_split_data = recv_data.split()
            if recv_split_data[0] == 'REGISTER':
                try:
                    encrypted = crypt.crypt(recv_split_data[2], "22") #교수님의 암호화 코드(패스워드 암호화)
                    cursor.execute("INSERT INTO members VALUES (?,?);", (recv_split_data[1], encrypted))#암호화하여 db에 insert
                    connect.commit()
                    conn.send("232 User register success".encode('utf-8'))
                    print("<< " + "232 User register success")
                except: #데이터베이스에 있는 사용자id일 경우 리턴
                    conn.send("510 User register fail".encode('utf-8'))
                    print("<< " + "510 User register fail")
            elif recv_split_data[0] == 'USER': #로그인
                try:
                    encrypted = crypt.crypt(recv_split_data[2], "22")
                    #사용자의 데이터를 암호화하여 비교하고 데이터베이스에서 select로 사용자의 id가 있는지 찾고 가져온다
                    cursor.execute("SELECT id, password FROM members WHERE id=?", (recv_split_data[1],))
                    user = cursor.fetchone() #결과값의 처음 데이터만 가져온다. id가 유니크키이기에 하나만 가져와도 된다
                    if user[1] == encrypted: #데이터베이스에 있는 것과 유저가 보낸데이터를 암호화한것을 비교
                        conn.send("230 User logged in".encode('utf-8'))
                        print("<< " + "230 User loggen in")
                        game_user = GameUser(game_user_count, recv_split_data[1])
                        login_users[conn] = recv_split_data[1] #login user id 저장
                        game_users_socket[game_user_count] = conn
                        game_users[game_user_count] = game_user
                        game_user_count = game_user_count + 1
                        print("game user count = " + str(game_user_count))
                    else:
                        conn.send("531 invalid user or password".encode('utf-8'))
                        print("<< " + "531 invalid user or password")
                except:
                    conn.send("531 invalid user or password".encode('utf-8'))
                    print("<< " + "531 invalid user or password")
            elif recv_split_data[0] == 'LIST': #리스트 데이터를 유저에게 전송
                user_list = ""
                if login_users:
                    for each in login_users:
                        user_list = user_list + login_users[each] + " "
                    conn.send(("231 Users: " + user_list).encode('utf-8'))
                    print("<< 231 Users: " + user_list)
            elif recv_split_data[0] == 'QUIT': #quit 요청을 받았을때
                conn.send(("221 service closeing server close this socket").encode('utf-8'))
                print("<< 221 service closeing server close this socket")
                del login_users[conn] #login된 유저딕셔너리에 있는 데이터 삭제
                users.remove(conn) #소켓 정보 삭제
                conn.close() #소켓 종료
                break

            elif recv_split_data[0] == 'FROM': #사용자가 보낸 FROM 메시지 처리
                for each in users:
                    if each is conn:
                        each.send(("200 OK").encode('utf-8'))
                        print("<< 200 OK")
                    else:
                        each.send(("299 " + recv_data).encode('utf-8'))
                        print("<< 299" + recv_data)

            elif recv_split_data[0] == 'GAME': #주사위 데이터 처리
                print("game data")
                location = game_user.location + int(recv_split_data[1])
                blue_marble.setUserLocation(game_user.user_id, game_user.location, int(recv_split_data[1]))
                if location >= 24:
                    game_user.location = location - 24
                else:
                    game_user.location = location

                conn.send(("236 " + game_user.user_name + " " + str(game_user.location) + " move event " + str(blue_marble.checkEvent(game_user.user_id, game_user.location)) + " "
                           + blue_marble.getLocationName(game_user.location)).encode('utf-8'))
                if game_user.user_id == 0: #상대방에게 자신의 캐릭터 위치 전송
                    game_users_socket[1].send(("237 " + game_user.user_name + " " + str(game_user.location) + " move event").encode('utf-8'))
                else:
                    game_users_socket[0].send(("237 " + game_user.user_name + " " + str(game_user.location) + " move event").encode('utf-8'))

            elif recv_split_data[0] == 'EVENT': #이벤트 처리후(자산 관리) 다음 상대방에게 턴을 넘겨줌
                print("----event data----")
                if recv_split_data[1] == 'BUY':
                    print(recv_data)
                    temp_money = game_user.money
                    game_user.money = temp_money - int(recv_split_data[2])
                    blue_marble.setBuildingOwner(game_user.user_id, recv_split_data[3])
                    if game_users[0].user_id == game_user.user_id:
                        print(game_user.user_id)
                        print("if")
                        print(game_user.user_name)
                        game_users_socket[1].send(("240 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[1].money)).encode('utf-8'))
                        game_users_socket[0].send(("239 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[1].money)).encode('utf-8'))
                    else:
                        print(game_user.user_id)
                        print("else")
                        print(game_user.user_name)
                        game_users_socket[1].send(("239 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[0].money)).encode('utf-8'))
                        game_users_socket[0].send(("240 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[0].money)).encode('utf-8'))

                elif recv_split_data[1] == 'NOTBUY':
                    if game_users[0].user_id == game_user.user_id:
                        game_users_socket[1].send(("240 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[1].money)).encode('utf-8'))
                        game_users_socket[0].send(("239 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[1].money)).encode('utf-8'))
                    else:
                        game_users_socket[1].send(("239 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[0].money)).encode('utf-8'))
                        game_users_socket[0].send(("240 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[0].money)).encode('utf-8'))

                elif recv_split_data[1] == 'TAX':
                    temp_money = game_user.money
                    game_user.money = temp_money + int(recv_split_data[2])
                    if game_users[0].user_id == game_user.user_id:
                        temp_money = game_users[1].money
                        game_users[1].money = temp_money - int(recv_split_data[2])
                        game_users_socket[1].send(("240 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[1].money)).encode('utf-8'))
                        game_users_socket[0].send(("239 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[1].money)).encode('utf-8'))
                    else:
                        temp_money = game_users[0].money
                        game_users[0].money = temp_money - int(recv_split_data[2])
                        game_users_socket[1].send(("239 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[0].money)).encode('utf-8'))
                        game_users_socket[0].send(("240 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[0].money)).encode('utf-8'))

                elif recv_split_data[1] == 'START':
                    temp_money = game_user.money
                    game_user.money = temp_money - int(recv_split_data[2])
                    if game_users[0].user_id == game_user.user_id:
                        game_users_socket[1].send(("240 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[1].money)).encode('utf-8'))
                        game_users_socket[0].send(("239 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[1].money)).encode('utf-8'))
                    else:
                        game_users_socket[1].send(("239 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[0].money)).encode('utf-8'))
                        game_users_socket[0].send(("240 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[0].money)).encode('utf-8'))

                elif recv_split_data[1] == 'HONG':
                    game_users_socket[1].send(("250 " + game_user.user_name + " WIN").encode('utf-8'))
                    game_users_socket[0].send(("250 " + game_user.user_name + " WIN").encode('utf-8'))

                elif recv_split_data[1] == 'SPACE':
                    rand_num = randint(1, 23)
                    location = game_user.location + rand_num
                    blue_marble.setUserLocation(game_user.user_id, game_user.location, rand_num)
                    if location >= 24:
                        game_user.location = location - 24
                    else:
                        game_user.location = location

                    if game_users[0].user_id == game_user.user_id:
                        game_users_socket[1].send(("240 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[1].money)).encode('utf-8'))
                        game_users_socket[0].send(("239 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[1].money)).encode('utf-8'))
                    else:
                        game_users_socket[1].send(("239 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[0].money)).encode('utf-8'))
                        game_users_socket[0].send(("240 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[0].money)).encode('utf-8'))


                elif recv_split_data[1] == 'ISLAND':
                    if game_users[0].user_id == game_user.user_id:
                        game_users_socket[1].send(("240 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[1].money)).encode('utf-8'))
                        game_users_socket[0].send(("239 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[1].money)).encode('utf-8'))
                    else:
                        game_users_socket[1].send(("239 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[0].money)).encode('utf-8'))
                        game_users_socket[0].send(("240 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[0].money)).encode('utf-8'))

                elif recv_split_data[1] == 'KEY':
                    if game_users[0].user_id == game_user.user_id:
                        game_users_socket[1].send(("240 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[1].money)).encode('utf-8'))
                        game_users_socket[0].send(("239 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[1].money)).encode('utf-8'))
                    else:
                        game_users_socket[1].send(("239 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[0].money)).encode('utf-8'))
                        game_users_socket[0].send(("240 " + game_user.user_name + " " + str(game_user.location) + " " + str(game_user.money) + " " + recv_split_data[3] + " " + str(game_users[0].money)).encode('utf-8'))

            if game_user_count == 2: #게임 스타트
                print("game start")
                for each in users:
                    each.send(("233 Start Game: " + login_users[game_users_socket[0]] + " " + login_users[game_users_socket[1]]).encode('utf-8'))
                game_user_count = -1



    except:#오류가 발생할 경우 유저와의 연결을 종료시킨다.
        users.remove(conn)
        del login_users[conn]
        conn.close()

while 1: #사용자들의 접속을 계속 받는 루프문
    conn, addr = s.accept()
    global users, login_users, game_users_socket
    print(str(conn) + " 접속")
    users.append(conn)
    threading._start_new_thread(service, (conn, )) #service 함수를 쓰레드로 실행
    pass



